///************************************************************************
/// <copyrigth>2018-2019 Corporation.All Rights Reserved</copyrigth>
/// <author>tangyingzhong</author>
/// <contact>tangyz114987@outlook.com</contact>
/// <version>v1.0.0</version>
/// <describe>
/// It is a video decoder which can automatically switch hard decoder and soft decoder 
///</describe>
/// <date>2021/6/26</date>
///***********************************************************************
#ifndef VIDEODECODER_H
#define VIDEODECODER_H

extern "C" {
#include <libavutil/frame.h>
#include <libavutil/avutil.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/common.h>
#include <libavutil/hwcontext.h>
#include <libavutil/imgutils.h>
}
#include "Model/Video/VideoSoftDecoder/IVideoSoftDecoder.h"
#include "Model/Video/VideoHardDecoder/IVideoHardDecoder.h"
#include "IVideoDecoder.h"

class VideoDecoder :public IVideoDecoder
{
public:
	// Construct the VideoDecoder
	VideoDecoder();

	// Detructe the VideoDecoder
	virtual ~VideoDecoder();

private:
	// Forbid the copy VideoDecoder
	VideoDecoder(const VideoDecoder& other) {	};

	// Forbid the assigment of VideoDecoder
	VideoDecoder& operator=(const VideoDecoder& other) { return *this; };

public:
	// Init the decoder
	virtual bool Init(VideoTypeEnum eVideoType, void* pWindowHandle = NULL);

	// Excute the decoding
	virtual bool Excute(uint8_t* pSrcData,
		int iSrcSize,
		uint8_t* pDst,
		int& iDstSize,
		int& iFrameWidth,
		int& iFrameHeight);

	// Flush the decode at the last frame decoding
	virtual void Flush();

private:
	// Is current system support hard decoder
	bool IsSupportHardDecode(VideoTypeEnum eVideoType);

	// Init soft decoder
	bool InitSoftDecoder(VideoTypeEnum eVideoType);

	// Init hard decoder
	bool InitHardDecoder(VideoTypeEnum eVideoType, void* pWindowHandle);

private:
	// Initialize the decoder
	void Initialize();

	// Destory the decoder
	void Destory();

	// Create soft decoder
	void CreateSoftDecoder();

	// Destory soft decoder
	void DestorySoftDecoder();

	// Create hard decoder
	void CreateHardDecoder();

	// Destory hard decoder
	void DestoryHardDecoder();

private:
	// Get the SoftDecoder
	inline IVideoSoftDecoder* GetSoftDecoder() const
	{
		return m_pSoftDecoder;
	}

	// Set the SoftDecoder
	inline void SetSoftDecoder(IVideoSoftDecoder* pSoftDecoder)
	{
		m_pSoftDecoder = pSoftDecoder;
	}

	// Get the HardDecoder
	inline IVideoHardDecoder* GetHardDecoder() const
	{
		return m_pHardDecoder;
	}

	// Set the HardDecoder
	inline void SetHardDecoder(IVideoHardDecoder* pHardDecoder)
	{
		m_pHardDecoder = pHardDecoder;
	}

	// Get the IsUseHardDecoder
	inline bool GetIsUseHardDecoder() const
	{
		return m_bIsUseHardDecoder;
	}

	// Set the IsUseHardDecoder
	inline void SetIsUseHardDecoder(bool bIsUseHardDecoder)
	{
		m_bIsUseHardDecoder = bIsUseHardDecoder;
	}

	// Get the disposed status
	inline bool GetDisposed() const
	{
		return m_bDisposed;
	}

	// Set the disposed status
	inline void SetDisposed(bool bDisposed)
	{
		m_bDisposed = bDisposed;
	}

private:
	// Soft decoder
	IVideoSoftDecoder* m_pSoftDecoder;
	
	// Hard decoder
	IVideoHardDecoder* m_pHardDecoder;
	
	// Is using hard decoder
	bool m_bIsUseHardDecoder;
	
	// Disposed status
	bool m_bDisposed;
};

#endif // VideoDecoder_H
